package geppetto.reordering.graph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import geppetto.cat.corpus.BilingualCorpus;
import geppetto.phraseHMM.WordTrie;
import geppetto.phraseHMM.phraseExtraction.extractedphrase.ExtractedPhrasePair;
import geppetto.phraseHMM.phraseExtraction.extractedphrase.ExtractedPhrasePairData;
import geppetto.phraseHMM.phraseExtraction.extractedphrase.ExtractedPhrasePairTable;
import geppetto.phraseHMM.phraseExtraction.extractedphrase.SentenceInfo;
import geppetto.phraseHMM.phraseExtraction.extractedphrase.data.ReorderingGraphData;
import geppetto.phraseTable.phrase.Phrase;
import geppetto.reordering.MSDOrientationCodes;
import geppetto.reordering.graph.scorers.DiscontinuousPenalty;
import geppetto.reordering.graph.scorers.UnweightedGraphScorer;

public class ReorderingGraph {
	protected int sentenceNumber = -1;
	protected ExtractedPhrasePair[] extractedPhrases;
	protected int[] source;
	protected int[] target;
	protected List<ExtractedPhrasePair>[] extractedPhrasesByTargetEndPosition;
	protected List<ExtractedPhrasePair>[] extractedPhrasesByTargetStartPosition;
	NumberOfPathsSparseMatrix pathsMatrixForward = new NumberOfPathsSparseMatrix();
	NumberOfPathsSparseMatrix pathsMatrixBackward = new NumberOfPathsSparseMatrix();
	//protected HashMap<ExtractedPhrasePair, Double> pathsToNode;
	//protected HashMap<ExtractedPhrasePair, Double> pathsFromNode;
	protected ExtractedPhrasePair startNode;
	protected ExtractedPhrasePair endNode;
	GraphWeightScorer scorer = new UnweightedGraphScorer();
	boolean pathsGeneratedForSandE = false;
	boolean allPathsGenerated = false;

	public ReorderingGraph(SentenceInfo sentence) {
		this(sentence.getExtractedPhrases(), sentence.getSourceSentence(), sentence.getForeingSentence(), sentence.getSentenceNumber());
	}

	public ReorderingGraph(ExtractedPhrasePair[] extractedPhrases, int[] source, int[] target, int sentenceNumber) {
		super();
		this.sentenceNumber = sentenceNumber;
		this.extractedPhrases = extractedPhrases;
		this.source = source;
		this.target = target;
		extractedPhrasesByTargetStartPosition = new ArrayList[target.length];
		extractedPhrasesByTargetEndPosition = new ArrayList[target.length];
		for(int i = 0; i < target.length; i++){
			extractedPhrasesByTargetEndPosition[i] = new ArrayList<ExtractedPhrasePair>();
			extractedPhrasesByTargetStartPosition[i] = new ArrayList<ExtractedPhrasePair>();
		}
		//pathsToNode = new HashMap<ExtractedPhrasePair, Double>();
		//pathsFromNode = new HashMap<ExtractedPhrasePair, Double>();
		for(ExtractedPhrasePair pair : extractedPhrases){
			extractedPhrasesByTargetStartPosition[pair.getForeignStartPos()].add(pair);
			extractedPhrasesByTargetEndPosition[pair.getForeignEndPos()].add(pair);
			//pathsToNode.put(pair, 0d);
			//pathsFromNode.put(pair, 0d);
		}
		if(extractedPhrases.length>0){
		startNode = new ExtractedPhrasePair(new int[0], new int[0], extractedPhrases[0].getSentenceNumber(), extractedPhrases[0].getSentenceSource(), extractedPhrases[0].getForeignSentence(), extractedPhrases[0].getSourceSentence(),-1,-1,-1,-1);
		startNode.setStartNode(true);
		//pathsFromNode.put(startNode, 0d);
		//pathsToNode.put(startNode, 1d);
		endNode = new ExtractedPhrasePair(new int[0], new int[0], extractedPhrases[0].getSentenceNumber(), extractedPhrases[0].getSentenceSource(), extractedPhrases[0].getForeignSentence() ,extractedPhrases[0].getSourceSentence(),source.length,source.length,target.length,target.length);
		endNode.setEndNode(true);
		//pathsFromNode.put(endNode, 1d);
		//pathsToNode.put(endNode, 0d);
		}
	}

	public void generateWeightedGraphPaths(){
		if(!pathsGeneratedForSandE){
			pathsMatrixForward.increment(startNode, startNode, scorer.scoreNode(startNode));
			pathsMatrixBackward.increment(endNode, endNode, scorer.scoreNode(endNode));

			//pathsToNode.put(startNode, scorer.scoreNode(startNode));
			//pathsFromNode.put(endNode, scorer.scoreNode(endNode));

			generatePathsToNodeTopologicWeighted();
			generatePathsFromNodeTopologicWeighted();

			/*double test = pathsToNode.get(endNode); 
		if(numberOfPaths != test){
			System.err.println("crap");
			System.err.println("n" + numberOfPaths);
			System.err.println("p" + test);
		}*/
			pathsGeneratedForSandE = true;
		}
	}

	public void generatePathsToNodeTopologicWeighted(){		
		for(int i = -1; i < extractedPhrasesByTargetEndPosition.length; i++){
			List<ExtractedPhrasePair> pairs = null; 
			if(i==-1){
				pairs = new LinkedList<ExtractedPhrasePair>();
				pairs.add(startNode);
			}
			else{
				pairs = extractedPhrasesByTargetEndPosition[i];
			}

			List<ExtractedPhrasePair> nodes = getFollowingNodes(i + 1);
			for(ExtractedPhrasePair p : pairs){
				for(ExtractedPhrasePair n : nodes){
					pathsMatrixForward.increment(startNode, n, pathsMatrixForward.get(startNode,p)*scorer.scoreNode(n)*scorer.scoreNextArc(p, n));
					//pathsToNode.put(n,pathsToNode.get(n) + pathsToNode.get(p)*scorer.scoreNode(n)*scorer.scoreNextArc(p, n));
				}
			}
		}
	}
	
	public void generatePathsFromNodeTopologicWeighted(){
		for(int i = extractedPhrasesByTargetStartPosition.length; i >= 0; i--){
			List<ExtractedPhrasePair> pairs = null; 
			if(i==extractedPhrasesByTargetStartPosition.length){
				pairs = new LinkedList<ExtractedPhrasePair>();
				pairs.add(endNode);
			}
			else{
				pairs = extractedPhrasesByTargetStartPosition[i];
			}
			List<ExtractedPhrasePair> nodes = getPreviousNodes(i - 1);
			for(ExtractedPhrasePair p : pairs){
				for(ExtractedPhrasePair n : nodes){
					pathsMatrixBackward.increment(endNode, n, pathsMatrixBackward.get(endNode,p)*scorer.scoreNode(n)*scorer.scorePrevArc(p, n));
					//pathsFromNode.put(n,pathsFromNode.get(n) + pathsFromNode.get(p)*scorer.scoreNode(n)*scorer.scorePrevArc(p, n));
				}
			}
		}
	}
	
	public void generateWeightedGraphAllPaths(){
		if(!allPathsGenerated){
			pathsMatrixForward.increment(startNode, startNode, scorer.scoreNode(startNode));
			pathsMatrixForward.increment(endNode, endNode, scorer.scoreNode(endNode));
			pathsMatrixBackward.increment(startNode, startNode, scorer.scoreNode(startNode));
			pathsMatrixBackward.increment(endNode, endNode, scorer.scoreNode(endNode));

			for(ExtractedPhrasePair pair : extractedPhrases){
				pathsMatrixForward.increment(pair, pair, scorer.scoreNode(pair));
				pathsMatrixBackward.increment(pair, pair, scorer.scoreNode(pair));
			}

			generateAllPathsToNodeTopologicWeighted();
			generateAllPathsFromNodeTopologicWeighted();

			pathsGeneratedForSandE = true;
			allPathsGenerated = true;
		}
	}
	
	public void generateAllPathsToNodeTopologicWeighted(){
		for(int i = -1; i < extractedPhrasesByTargetEndPosition.length; i++){
			List<ExtractedPhrasePair> pairs = null; 
			if(i==-1){
				pairs = new LinkedList<ExtractedPhrasePair>();
				pairs.add(startNode);
			}
			else{
				pairs = extractedPhrasesByTargetEndPosition[i];
			}

			List<ExtractedPhrasePair> nodes = getFollowingNodes(i + 1);
			for(ExtractedPhrasePair p : pairs){
				for(ExtractedPhrasePair n : nodes){
					ExtractedPhrasePair[] phrasesWithP = pathsMatrixForward.getPathsToA(p).keySet().toArray(new ExtractedPhrasePair[0]);
					for(ExtractedPhrasePair pathWithP : phrasesWithP){
						pathsMatrixForward.increment(pathWithP, n, pathsMatrixForward.get(pathWithP,p)*scorer.scoreNode(n)*scorer.scoreNextArc(p, n));
					}
				}
			}
		}
	}
	
	public void generateAllPathsFromNodeTopologicWeighted(){
		for(int i = extractedPhrasesByTargetStartPosition.length; i >= 0; i--){
			List<ExtractedPhrasePair> pairs = null; 
			if(i==extractedPhrasesByTargetStartPosition.length){
				pairs = new LinkedList<ExtractedPhrasePair>();
				pairs.add(endNode);
			}
			else{
				pairs = extractedPhrasesByTargetStartPosition[i];
			}
			List<ExtractedPhrasePair> nodes = getPreviousNodes(i - 1);
			for(ExtractedPhrasePair p : pairs){
				for(ExtractedPhrasePair n : nodes){
					ExtractedPhrasePair[] phrasesWithP = pathsMatrixBackward.getPathsToA(p).keySet().toArray(new ExtractedPhrasePair[0]);
					for(ExtractedPhrasePair pathWithP : phrasesWithP){
						pathsMatrixBackward.increment(pathWithP, n, pathsMatrixBackward.get(pathWithP,p)*scorer.scoreNode(n)*scorer.scorePrevArc(p, n));						
					}
				}
			}
		}
	}

	public Double getNumberOfPaths() {
		return getNumberOfPathsForward(startNode, endNode);
	}

	public Double getNumberOfPathsForward(ExtractedPhrasePair A, ExtractedPhrasePair B){
		return pathsMatrixForward.get(A, B);
	}

	public Double getNumberOfPathsBackward(ExtractedPhrasePair A, ExtractedPhrasePair B){
		return pathsMatrixForward.get(A, B);
	}
	
	public Double getPathsToNode(ExtractedPhrasePair e){
		return pathsMatrixForward.get(startNode,e);
	}

	public Double getPathsFromNode(ExtractedPhrasePair e){
		return pathsMatrixBackward.get(endNode,e);
	}
	
	public Double getNumberOfPathsForIndexes(int from, int to){
		List<ExtractedPhrasePair> phrasePairsStartingFrom = extractedPhrasesByTargetStartPosition[from];
		List<ExtractedPhrasePair> phrasePairsEndingTo = extractedPhrasesByTargetEndPosition[to];
		double numberOfPaths = 0;
		for(ExtractedPhrasePair pairFrom : phrasePairsStartingFrom){
			for(ExtractedPhrasePair pairTo : phrasePairsEndingTo){
				numberOfPaths += pathsMatrixForward.get(pairFrom, pairTo);
			}
		}
		return numberOfPaths;
	}

	public List<ExtractedPhrasePair> getFollowingNodes(int endIndex){
		ArrayList<ExtractedPhrasePair> followingNodes = new ArrayList<ExtractedPhrasePair>();
		int endMinIndex=target.length - 1;
		while(endIndex <= endMinIndex){
			for(ExtractedPhrasePair pair : extractedPhrasesByTargetStartPosition[endIndex]){
				followingNodes.add(pair);
				//endMinIndex = Math.min(endMinIndex, pair.getForeignEndPos());
			}
			if(!extractedPhrasesByTargetEndPosition[endIndex].isEmpty() && !followingNodes.isEmpty()){
				endMinIndex = endIndex;
			}
			endIndex++;
		}
		if(followingNodes.isEmpty() && endIndex == target.length){
			followingNodes.add(endNode);
		}
		return followingNodes;
	}

	public List<ExtractedPhrasePair> getFollowingNodes(ExtractedPhrasePair e){
		int index = e.getForeignEndPos() + 1;
		return getFollowingNodes(index);		
	}

	public List<ExtractedPhrasePair> getPreviousNodes(int startIndex){		
		ArrayList<ExtractedPhrasePair> previousNodes = new ArrayList<ExtractedPhrasePair>();
		int endMinIndex = 0;
		while(startIndex >= endMinIndex){
			for(ExtractedPhrasePair pair : extractedPhrasesByTargetEndPosition[startIndex]){
				previousNodes.add(pair);
				//endMinIndex = Math.max(endMinIndex, pair.getForeignStartPos());

			}
			if(!extractedPhrasesByTargetStartPosition[startIndex].isEmpty() && !previousNodes.isEmpty()){
				endMinIndex = startIndex;
			}
			startIndex--;
		}
		if(previousNodes.isEmpty() && startIndex == -1){
			previousNodes.add(startNode);
		}
		return previousNodes;		
	}

	public List<ExtractedPhrasePair> getPreviousNodes(ExtractedPhrasePair e){
		int index = e.getForeignStartPos() - 1;
		return getPreviousNodes(index);		
	}
	
	public int getOrientation(ExtractedPhrasePair e1, ExtractedPhrasePair e2){
		if(isStartNode(e1) || isStartNode(e2) || isEndNode(e1) || isEndNode(e2)){
			return MSDOrientationCodes.MONO_CODE;
		}
		if(e1.getForeignEndPos() + 1 != e2.getForeignStartPos()){
			return MSDOrientationCodes.OTHER_CODE;
		}
		if(e1.getSourceEndPos() + 1 == e2.getSourceStartPos()){
			return MSDOrientationCodes.MONO_CODE;
		}
		if(e2.getSourceEndPos() + 1 == e1.getSourceStartPos()){
			return MSDOrientationCodes.SWAP_CODE;
		}
		return MSDOrientationCodes.OTHER_CODE;
	}


	public void printPath(LinkedList<ExtractedPhrasePair> visited){
		for(ExtractedPhrasePair node : visited){
			System.out.print("[(" + node.getSourceStartPos() + ","+ node.getSourceEndPos() + ")(" + node.getForeignStartPos() + "," + node.getForeignEndPos() + ")]" );
		}
		System.out.println();
	}

	public void printGraph(){
		System.out.println("forward:");
		for(int i = -1; i < extractedPhrasesByTargetEndPosition.length; i++){
			List<ExtractedPhrasePair> pairs = null; 
			if(i==-1){
				pairs = new LinkedList<ExtractedPhrasePair>();
				pairs.add(startNode);
			}
			else{
				pairs = extractedPhrasesByTargetEndPosition[i];
			}
			List<ExtractedPhrasePair> nodes = getFollowingNodes(i + 1);			
			for(ExtractedPhrasePair pair : pairs){
				for(ExtractedPhrasePair node : nodes){
					//System.out.print("[(" + pair.getSourceStartPos() + ","+ pair.getSourceEndPos() + ")(" + pair.getForeignStartPos() + "," + pair.getForeignEndPos() + "), a:" + pathsToNode.get(pair) + ",b:"+ pathsFromNode.get(pair) +"]" );
					System.out.print("[(" + pair.getSourceStartPos() + ","+ pair.getSourceEndPos() + ")(" + pair.getForeignStartPos() + "," + pair.getForeignEndPos() + "), a:" + pathsMatrixForward.get(startNode,pair) + ",b:"+ pathsMatrixForward.get(endNode,pair) +"]" );
					System.out.print("->");
					//System.out.println("[(" + node.getSourceStartPos() + ","+ node.getSourceEndPos() + ")(" + node.getForeignStartPos() + "," + node.getForeignEndPos() + "), a:" + pathsToNode.get(node) + ",b:"+ pathsFromNode.get(node) +"]" );
					System.out.println("[(" + node.getSourceStartPos() + ","+ node.getSourceEndPos() + ")(" + node.getForeignStartPos() + "," + node.getForeignEndPos() + "), a:" + pathsMatrixForward.get(startNode,node) + ",b:"+ pathsMatrixForward.get(endNode,node) +"]" );
				}
			}
		}
		System.out.println("backwards:");
		for(int i = extractedPhrasesByTargetStartPosition.length-1; i >= 0; i--){
			List<ExtractedPhrasePair> pairs = extractedPhrasesByTargetStartPosition[i];
			List<ExtractedPhrasePair> nodes = getPreviousNodes(i - 1);
			for(ExtractedPhrasePair pair : pairs){
				for(ExtractedPhrasePair node : nodes){
					//System.out.print("[(" + pair.getSourceStartPos() + ","+ pair.getSourceEndPos() + ")(" + pair.getForeignStartPos() + "," + pair.getForeignEndPos() + "), a:" + pathsToNode.get(pair) + ",b:"+ pathsFromNode.get(pair) +"]" );
					System.out.print("[(" + pair.getSourceStartPos() + ","+ pair.getSourceEndPos() + ")(" + pair.getForeignStartPos() + "," + pair.getForeignEndPos() + "), a:" + pathsMatrixBackward.get(startNode, pair) + ",b:"+ pathsMatrixBackward.get(endNode,pair) +"]" );
					System.out.print("->");
					//System.out.println("[(" + node.getSourceStartPos() + ","+ node.getSourceEndPos() + ")(" + node.getForeignStartPos() + "," + node.getForeignEndPos() + "), a:" + pathsToNode.get(node) + ",b:"+ pathsFromNode.get(node) +"]" );
					System.out.println("[(" + node.getSourceStartPos() + ","+ node.getSourceEndPos() + ")(" + node.getForeignStartPos() + "," + node.getForeignEndPos() + "), a:" + pathsMatrixBackward.get(startNode, node) + ",b:"+ pathsMatrixBackward.get(endNode,node) +"]" );
				}
			}
		}
	}
	
	public void printPathMatrices(){
		System.out.println("forward:");
		
	}
	

	public static void main(String[] args) throws Exception{
		ExtractedPhrasePair[] phrases = getTestPhrases();
		ReorderingGraph graph = (ReorderingGraph)phrases[0].getSentenceInfo().getCustomInfo("reordering-graph");
		int i = 0;
		for(ExtractedPhrasePair pair : phrases){
			i++;
			System.out.println(i + " - " + graph.getPathsToNode(pair) + " , " + graph.getPathsFromNode(pair));
		}
		i=0;
		for(ExtractedPhrasePair pair : phrases){
			i++;
			System.out.println(i + " - " + graph.getNumberOfPathsForward(phrases[1],pair) + " , " + graph.getPathsFromNode(pair));
		}
		System.out.println("number of paths next = " + graph.getNumberOfPaths());
		System.out.println("number of paths between 1 and 7 =" + graph.getNumberOfPathsForIndexes(1, 7));
		System.out.println("number of paths between 2 and 5 =" + graph.getNumberOfPathsForIndexes(2, 5));
		/*System.out.println("p1 - p3 next ->" + graph.getOrientation(phrases[0], phrases[2]));
		System.out.println("p1 - p4 next ->" + graph.getOrientation(phrases[0], phrases[3]));
		System.out.println("p1 - p5 next ->" + graph.getOrientation(phrases[0], phrases[4]));
		System.out.println("p1 - p6 next ->" + graph.getOrientation(phrases[0], phrases[5]));
		System.out.println("p1 - p7 next ->" + graph.getOrientation(phrases[0], phrases[6]));
		System.out.println("p3 - p8 next ->" + graph.getOrientation(phrases[2], phrases[7]));
		System.out.println("p4 - p9 next ->" + graph.getOrientation(phrases[3], phrases[8]));
		System.out.println("p4 - p10 next ->" + graph.getOrientation(phrases[3], phrases[9]));
		System.out.println("p5 - p11 next ->" + graph.getOrientation(phrases[4], phrases[10]));
		System.out.println("p6 - p12 next ->" + graph.getOrientation(phrases[5], phrases[11]));
		System.out.println("p6 - p13 next ->" + graph.getOrientation(phrases[5], phrases[12]));*/
	}

	public ExtractedPhrasePair getStartNode() {
		return startNode;
	}

	public ExtractedPhrasePair getEndNode() {
		return endNode;
	}

	public void setScorer(GraphWeightScorer s){
		scorer = s;
	}

	public GraphWeightScorer getScorer() {
		return scorer;
	}

	public static boolean isStartNode(ExtractedPhrasePair pair) {
		return pair.isStartNode();
	}

	public static boolean isEndNode(ExtractedPhrasePair pair){
		return pair.isEndNode();
	}

	public static ExtractedPhrasePair[] getTestPhrases(){
		ExtractedPhrasePair p0 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],0,0,0,0);
		ExtractedPhrasePair p1 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],1,1,1,1);
		ExtractedPhrasePair p2 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],1,7,1,7);
		ExtractedPhrasePair p3 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],4,4,2,2);
		ExtractedPhrasePair p4 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],4,5,2,3);
		ExtractedPhrasePair p5 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],4,6,2,4);
		ExtractedPhrasePair p6 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],4,7,2,5);
		ExtractedPhrasePair p7 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],2,7,2,7);
		ExtractedPhrasePair p8 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],5,5,3,3);
		ExtractedPhrasePair p9 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],6,6,4,4);
		ExtractedPhrasePair p10 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],6,7,4,5);
		ExtractedPhrasePair p11 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],7,7,5,5);
		ExtractedPhrasePair p12 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],2,2,6,6);
		ExtractedPhrasePair p13 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],2,3,6,7);
		ExtractedPhrasePair p14 = new ExtractedPhrasePair(new int[8], new int[8], 1, BilingualCorpus.TRAIN_CORPUS, new int[8], new int[8],3,3,7,7);
		ExtractedPhrasePair[] phrases = new ExtractedPhrasePair[]{p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14};
		SentenceInfo info = new SentenceInfo(1,new int[8], new int[8],phrases);
		for(ExtractedPhrasePair pair : phrases){
			pair.setSentenceInfo(info);
			pair.setScore(1);
		}
		info.setCustomInfo("reordering-graph", new ReorderingGraph(info));

		DiscontinuousPenalty penalty = new DiscontinuousPenalty();
		((ReorderingGraph)info.getCustomInfo("reordering-graph")).setScorer(new UnweightedGraphScorer(){
			@Override
			public double scoreNode(ExtractedPhrasePair to) {
				if(to.getForeignEndPos() == -1 || to.getForeignEndPos() == to.getForeignSentence().length){
					return 1;
				}
				return to.getScore();
			}
		});
		((ReorderingGraph)info.getCustomInfo("reordering-graph")).generateWeightedGraphAllPaths();
		((ReorderingGraph)info.getCustomInfo("reordering-graph")).printGraph();
		return phrases;
	}

	public ReorderingGraphEdge[] getAllEdges(){		
		LinkedList<ReorderingGraphEdge> edges = new LinkedList<ReorderingGraphEdge>();
		for(int i = -1; i < extractedPhrasesByTargetEndPosition.length; i++){
			List<ExtractedPhrasePair> pairs = null; 
			if(i==-1){
				pairs = new LinkedList<ExtractedPhrasePair>();
				pairs.add(startNode);
			}
			else{
				pairs = extractedPhrasesByTargetEndPosition[i];
			}

			List<ExtractedPhrasePair> nodes = getFollowingNodes(i + 1);
			for(ExtractedPhrasePair p : pairs){
				for(ExtractedPhrasePair n : nodes){
					edges.add(new ReorderingGraphEdge(p,n));
				}
			}
		}
		return edges.toArray(new ReorderingGraphEdge[0]);
	}
}
